#include <nxos.h>

#define TEST_THREAD_NR 32

NX_U32 ThreadHandler(void *arg)
{
    int index = (int)arg;
    NX_TlsSetValue(index, (void *) NX_ThreadGetCurrentId());
    NX_U32 value = (NX_U32)NX_TlsGetValue(index);
    NX_Printf("thread tls:%d\n", value);
    NX_ASSERT(value == NX_ThreadGetCurrentId());
    NX_Printf("thread exit:%d\n", NX_ThreadGetCurrentId());
    return 0;
}

NX_Error TEST_TLS(char *cmdline)
{
    NX_Solt solt;
    NX_Error err;
    NX_Size i;

    /* test all tls */
    for (i = 0; i < NX_TLS_MAX_NR + 5; i++)
    {
        int index = NX_TlsAlloc();
        if (index >= 0)
        {
            NX_TlsSetValue(index, (void *) i);
            void * value = NX_TlsGetValue(index);
            NX_Printf("tls:%p\n", value);
        }
        else
        {
            NX_Printf("index[%d] no tls!\n", i);
        }
    }
    /* free tls */
    for (i = 0; i < NX_TLS_MAX_NR + 5; i++)
    {
        err = NX_TlsFree(i);
        if (err != NX_EOK)
        {
            NX_Printf("tls[%d] free failed!\n", i);
        }
    }

    /* create some tls */

    int tls = NX_TlsAlloc();
    if (tls < 0)
    {
        NX_Printf("index[%d] no tls!\n", tls);
    }

    for (i = 0; i < TEST_THREAD_NR; i++)
    {
        solt = NX_ThreadCreate(NX_NULL, ThreadHandler, (void *)tls, 0);
        if (solt < 0)
        {
            return NX_ERROR;
        }
    }

    NX_ThreadSleep(3000);
    // NX_ThreadWait(solt, NX_NULL);

    NX_TlsFree(tls);

    /* test errno value */
    NX_ErrorSet(NX_EOK);
    err = NX_ErrorGet();
    NX_Printf("err:%d val:%d\n", err, NX_ErrorValue);

    NX_ErrorSet(NX_ENOSRCH);
    err = NX_ErrorGet();
    NX_Printf("err:%d val:%d\n", err, NX_ErrorValue);

    NX_ErrorSet(NX_EINVAL);
    err = NX_ErrorGet();
    NX_Printf("err:%d val:%d\n", err, NX_ErrorValue);

    NX_TlsSetExtension((void *)0x12345678);
    NX_Printf("extension:%p\n", NX_TlsGetExtension());

    NX_Printf("test done!\n");

    return NX_EOK;
}
